package com.xiaoyao.login.listener;

import com.xiaoyao.login.pojo.DomainObject;
import org.springframework.context.ApplicationContext;

import javax.persistence.*;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;

/**
 * @Classname DomainObjectListenerProxy
 * @Description TODO
 * @Date 2022/4/20 17:04
 * @Created by Lenovo
 */
public class DomainObjectListenerProxy {
    private List<DomainObjectListener> listenerList = Collections.emptyList();

    public DomainObjectListenerProxy() {
        Class<?> springApplicationListenerClass;
        String className = "com.xiaoyao.login.listener.SpringApplicationListener";
        try {
            springApplicationListenerClass = Class.forName(className);
        } catch (Exception e) {
            throw new IllegalStateException("failed to resolve class: " + className, e);
        }

        try {
            Method addListenerMethod = springApplicationListenerClass.getMethod("addListener", Consumer.class);
            addListenerMethod.invoke(null, (Consumer<ApplicationContext>) applicationContext -> loadListeners(applicationContext));
        } catch (Exception e) {
            throw new IllegalStateException("failed to load DomainObjectListeners", e);
        }
    }

    private void loadListeners(ApplicationContext context) {
        Collection<DomainObjectListener> col = context.getBeansOfType(DomainObjectListener.class).values();
        List<DomainObjectListener> list = new ArrayList<>(col);
        Collections.sort(list);
        this.listenerList = list;
    }

    @PrePersist
    public void prePersist(Object domainObject) {
        for (DomainObjectListener listener : listenerList) {
            if (listener.supports(domainObject))
                listener.prePersist((DomainObject)domainObject);
        }
    }

    @PostPersist
    public void postPersist(Object domainObject) {
        for (DomainObjectListener listener : listenerList) {
            if (listener.supports(domainObject))
                listener.postPersist((DomainObject)domainObject);
        }
    }

    @PreUpdate
    public void preUpdate(Object domainObject) {
        for (DomainObjectListener listener : listenerList) {
            if (listener.supports(domainObject))
                listener.preUpdate((DomainObject)domainObject);
        }
    }

    @PostUpdate
    public void postUpdate(Object domainObject) {
        for (DomainObjectListener listener : listenerList) {
            if (listener.supports(domainObject))
                listener.postUpdate((DomainObject)domainObject);
        }
    }

    @PreRemove
    public void preRemove(Object domainObject) {
        for (DomainObjectListener listener : listenerList) {
            if (listener.supports(domainObject))
                listener.preRemove((DomainObject)domainObject);
        }
    }

    @PostRemove
    public void postRemove(Object domainObject) {
        for (DomainObjectListener listener : listenerList) {
            if (listener.supports(domainObject))
                listener.postRemove((DomainObject)domainObject);
        }
    }
}
